package client;

import java.io.IOException;

import comm.*;
import chess.*;
import thinker.*;
import gui.*;

public class Client extends Thread {

	private static Communicator comm;
	private static Thinker thinker;
	private static ChessBoard board;
	private static Gui gui;
	private static ChessInfo nextMove;

	private static byte color;
	private static boolean waiting;
	private static boolean gameOver;

	public static boolean debug = false;

	public static void main(String args[]) throws Exception {

		color = ChessBoard.NONE;

		gui = new Gui();
		while (true) {
			while (!gui.isNet() && !gui.isLocal())
				;
			{
				if (comm == null)
					comm = new Communicator();
				prepare();
				board = new ChessBoard();
				gaming();

				if (debug) {
					board.print();
				}
			}
		}
	}

	private static void prepare() throws Exception {
		gameOver = false;
		nextMove = null;
		// TODO ask for first or second player
		Message m = new Message(Message.COMM_MSG_GAME_REQUIRE_START);
		RejectInfo r;
		waiting = false;
		while (true) {
			if (!waiting) {
				sleep(1000);
				comm.sendMsg(new Message(Message.COMM_MSG_GAME_REQUIRE_START));
				waiting = true;
			}
			m = comm.recMsg();
			switch (m.msg) {
			case Message.COMM_MSG_FIRST:
				color = ChessBoard.BLACK;
				break;
			case Message.COMM_MSG_SECOND:
				color = ChessBoard.WHITE;
				break;
			case Message.COMM_MSG_REJECTED:
				r = comm.recRejectInfo();
				handleRej(r, null);
				waiting = false;
				break;
			case Message.COMM_MSG_GAME_START:
				if (color != ChessBoard.NONE)
					return;
			}
		}
	}

	private static void gaming() throws Exception {
		Message m;
		ChessInfo c;
		RejectInfo r;
		gui.setColor(color);
		thinker = new Thinker(color, gui);
		waiting = false;
		while (true) {
			if (!waiting && (board.turn == color) && !gameOver) {
				comm.sendMsg(new Message(Message.COMM_MSG_CHESS));
				nextMove = thinker.nextMove(board);
				comm.sendChessInfo(nextMove);
				waiting = true;
			}
			m = comm.recMsg();
			switch (m.msg) {
			case Message.COMM_MSG_ACCEPT:
				break;
			case Message.COMM_MSG_REJECTED:
				r = comm.recRejectInfo();
				handleRej(r, nextMove);
				break;
			case Message.COMM_MSG_CHESS:
				c = comm.recChessInfo();
				gui.chess(c.color, c.col, c.row);
				board.update(c);
				waiting = false;
				break;
			case Message.COMM_MSG_WIN:
			case Message.COMM_MSG_LOSE:
			case Message.COMM_MSG_DRAW:
				gameOver = true;
				gui.gameOver(m.msg);
				break;
			case Message.COMM_MSG_TIMEOUT:
				waiting = true;
				break;
			}
			if (gameOver)
				break;
		}
	}

	private static void handleRej(RejectInfo r, ChessInfo c) throws IOException {
		if (r.solution == RejectInfo.SOLUTION_NOACTION) {
			return;
		}
		else {
			switch (r.parameter) {
			case Message.COMM_MSG_DONOTHING:
				return;
			case Message.COMM_MSG_FIRST:
			case Message.COMM_MSG_SECOND:
			case Message.COMM_MSG_GAME_REQUIRE_START:
				comm.sendMsg(new Message(r.parameter));
				break;
			case Message.COMM_MSG_CHESS:
				if (r.reason == RejectInfo.REJECT_REASON_INVALID_CHESS) {
					waiting = false;
				}
				else {
					if (c != null) {
						comm.sendMsg(new Message(r.parameter));
						comm.sendChessInfo(c);
						waiting = true;
					}
					else {
						waiting = false;
					}
				}
			}
		}
	}

}
